/*
 * 函数回调类型：接受一个可选参数，返回任意值
 * */
type ICallback = (arg?: unknown) => unknown;

/*
 * 回调函数数组类型
 * */
type ICallbacks = ICallback[];

/*
 * 事件容器接口：键为事件名，值为回调函数数组
 * */
interface IEvents {
  [key: string]: ICallbacks;
}

function creatEmitter() {
  /*
   * 存储自定义事件的容器
   * 容器结构：
   *  {
   * 事件名称: [回调函数1, 回调函数2, ...]
   * }
   * */
  const events = {};
  return {
    // 绑定自定义事件
    // 参数：eventName自定义事件名称，callback自定义事件回调函数
    on(eventName: string, callback: ICallback) {
      if (events[eventName]) {
        events[eventName].push(callback);
      }
      events[eventName] = [callback];
    },
    // 解绑自定义事件
    off(eventName: string, callback?: ICallback) {
      /*
       * off(eventName)解绑该事件（eventName）的所有回调函数
       * off(eventName,callback)解绑该事件（eventName）的一个回调函数（callback）*/
      const callbacks = events[eventName];
      if (!callbacks) {
        // return;
        throw new Error(`${eventName}自定义事件不存在~`);
      }
      if (callbacks) {
        events[eventName] = callbacks.filter(item => item !== callback);
      } else {
        // 解绑所有事件
        delete events[eventName];
      }
    },
    // 触发自定义事件
    emit(eventName: string, arg?: unknown) {
      const callbacks = events[eventName];
      if (!callbacks) {
        // return;
        throw new Error(`${eventName}自定义事件不存在~`);
      }
      // 遍历所有回调函数并执行
      callbacks.forEach(cb => cb(arg));
    },
  }
}

// 创建全局唯一的时间总线实例
const globalEmitter = creatEmitter();

// 导出默认值，供其他模块使用
export default globalEmitter;
